package org.campuscontent.util;

import java.awt.Point;
import java.awt.dnd.DnDConstants;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import org.campuscontent.model.Exercise;
import org.campuscontent.model.Problem;
import org.campuscontent.ui.ExerciseTree;

public class DefaultTreeTransferHandler extends AbstractTreeTransferHandler
{

	public DefaultTreeTransferHandler(ExerciseTree tree, int action)
	{
		super(tree, action, true);
	}

	public boolean canPerformAction(ExerciseTree target,
			DefaultMutableTreeNode draggedNode, int action, Point location)
	{
		TreePath pathTarget = target.getPathForLocation(location.x, location.y);


		if (pathTarget == null)
		{
			target.setSelectionPath(null);
			return (false);
		}
		if (draggedNode==draggedNode.getRoot())
		{
			target.setSelectionPath(null);
			return false;
		}
		
		//the draggedNode could be a problem or exercise,
		//if is problem, then the dragged node can be put under root node or exercise node
		//if is exercise,then the dragged node can be put under root only in copy mode.
		if (draggedNode.getParent()==draggedNode.getRoot())
		{
			DefaultMutableTreeNode nodeDragged = (DefaultMutableTreeNode)draggedNode.getUserObject();
			if (nodeDragged.getUserObject() instanceof Problem)
				//then if the target is exercise or root then return true else return false
			{
				DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) pathTarget.getLastPathComponent();

				if (parentNode==parentNode.getRoot()) // target node is root
				{
					if (action == DnDConstants.ACTION_COPY)    // no move action allowed 
					{
						target.setSelectionPath(pathTarget);
						return true;
					}
					else
					{
						target.setSelectionPath(null);
						return false;					
					}
				}
				
				//if the leaf node is exercise than return true
				DefaultMutableTreeNode nodeTarget = (DefaultMutableTreeNode)parentNode.getUserObject();
				if (nodeTarget.getUserObject() instanceof Problem)
				{
					target.setSelectionPath(null);
					return false;					
				}
				else               // target node is exercise
				{
					return (true);
				}
			}	
			else
			{
				if (nodeDragged.getUserObject() instanceof Exercise)
				{
					DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) pathTarget.getLastPathComponent();
					if (parentNode==parentNode.getRoot())
					{
						if (action == DnDConstants.ACTION_COPY)    // no move action allowed 
						{
							target.setSelectionPath(pathTarget);
							return true;
						}
						else
						{
							target.setSelectionPath(null);
							return false;					
						}
					}
					else
					{
						target.setSelectionPath(null);
						return false;
					}
				}

			}
		}
				
		if (((DefaultMutableTreeNode) pathTarget.getLastPathComponent())
				.isLeaf())
		{
			DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) pathTarget.getLastPathComponent();
			//if the leaf node is exercise than return true
			DefaultMutableTreeNode nodeTemp = (DefaultMutableTreeNode)parentNode.getUserObject();
			if (nodeTemp.getUserObject() instanceof Exercise)
			{
				return true;
			}
			else
			{
				target.setSelectionPath(null);
				return (false);
			}
			
		}

		if (action == DnDConstants.ACTION_COPY)
		{
			target.setSelectionPath(pathTarget);
			return (true);
		} else if (action == DnDConstants.ACTION_MOVE)
		{
			DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) pathTarget
					.getLastPathComponent();
			if (draggedNode.isRoot() || parentNode == draggedNode.getParent()
					|| draggedNode.isNodeDescendant(parentNode))
			{
				target.setSelectionPath(null);
				return (false);
			} else
			{
				target.setSelectionPath(pathTarget);
				return (true);
			}
		} else
		{
			target.setSelectionPath(pathTarget);
			return (false);
		}
	}

	public boolean executeDrop(ExerciseTree target,
			DefaultMutableTreeNode draggedNode,
			DefaultMutableTreeNode newParentNode, int action)
	{
		if (action == DnDConstants.ACTION_COPY)
		{
			DefaultMutableTreeNode newNode = ExerciseTree.makeDeepCopy(draggedNode);
			((DefaultTreeModel) target.getModel()).insertNodeInto(newNode,
					newParentNode, newParentNode.getChildCount());
			TreePath treePath = new TreePath(newNode.getPath());
			target.scrollPathToVisible(treePath);
			target.setSelectionPath(treePath);
			return (true);
		}
		if (action == DnDConstants.ACTION_MOVE)
		{
			draggedNode.removeFromParent();
			((DefaultTreeModel) target.getModel()).insertNodeInto(draggedNode,
					newParentNode, newParentNode.getChildCount());
			TreePath treePath = new TreePath(draggedNode.getPath());
			target.scrollPathToVisible(treePath);
			target.setSelectionPath(treePath);
			return (true);
		}
		return (false);
	}

}
